home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 …ember: Reference Library / Dev.CD Dec 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 26 / develop issue 26 code / truffles - display mgr. / sprocket / experimentalstuff / uappleobject.cp < prev    next >
Encoding:
Text File  |  1996-06-05  |  13.2 KB  |  595 lines

  1. // UAppleObject.cp
  2. // by Eric Berdahl
  3. // AppleLink: BERDAHL
  4. // Interget: eric_berdahl@taligent.com
  5. // May XX, 1992
  6. //
  7. // Copyright © 1992 Eric M. Berdahl
  8. // All rights reserved.
  9. //
  10. // LICENSE
  11. //
  12. // UAppleObject is provided under the ego-ware™ system.  If you send me a note
  13. // telling me how cool you think it UAppleObject is, you may incorporate it into
  14. // any product you like (six-packs of good beer are also acceptable, no C.O.D.
  15. // shipments, please).  Also, you must keep all copyright and other notices in
  16. // the source code, especially MY NAME (The system is called ego-ware™.  Get it?).
  17.  
  18.  
  19. #ifndef __AEOBJECTS__
  20. #include <AEObjects.h>
  21. #endif
  22.  
  23. #ifndef    __EXCEPTIONS__
  24. #include "Exceptions.h"
  25. #endif
  26.  
  27. #ifndef __RESOURCES__
  28. #include <Resources.h>
  29. #endif
  30.  
  31. #ifndef _UAPPLEOBJECT_
  32. #include "UAppleObject.h"
  33. #endif
  34.  
  35.  
  36. // This unit requires a definition for DEBUG (indicating whether or not you
  37. // want debugging code compiled in).  If you don’t set the flag, I’ll just 
  38. // assume you don’t want any.
  39. #ifndef DEBUG
  40. #define    DEBUG 0
  41. #endif
  42.  
  43. //--------------------------------------------------------------------------------
  44. // TAppleObjectDispatcher
  45. //--------------------------------------------------------------------------------
  46.  
  47. TAppleObjectDispatcher* TAppleObjectDispatcher::fgDispatcher = nil;
  48. Boolean TAppleObjectDispatcher::fgInited = false;
  49.  
  50.  
  51. TAppleObjectDispatcher::TAppleObjectDispatcher()
  52. {
  53.     fDisposalList = nil;
  54.     fDisposalListSize = 0;
  55.     fApplication = nil;
  56. }
  57.  
  58.  
  59. TAppleObjectDispatcher::~TAppleObjectDispatcher()
  60. {
  61.     if (fDisposalList != nil)
  62.         DisposeHandle((Handle) fDisposalList);
  63. }
  64.  
  65. struct MAEventTableRec
  66. {
  67.     OSType theClass;
  68.     OSType theID;
  69.     long theValue;
  70. };
  71. typedef MAEventTableRec* MAEventTablePointer;
  72.  
  73. void TAppleObjectDispatcher::Install()
  74. {
  75.     if (fgDispatcher != nil)
  76.         FailOSErr(errAppleObjectDispatcherAlreadyInstalled);
  77.  
  78.     Try
  79.     {
  80.         if (!fgInited)
  81.         {
  82.             AEObjectInit();
  83.             fgInited = true;
  84.         }
  85.  
  86.         fgDispatcher = this;
  87.  
  88.         // Install AppleEvent handlers from all aedt resources
  89.         // Look for all AppleEvent dispatch tables… 
  90.         short numberOfTables = Count1Resources('aedt');
  91.         FailResError();
  92.  
  93.         for (short tableIndex = 1; tableIndex <= numberOfTables; ++tableIndex)
  94.         {
  95.             Handle tableHandle = Get1IndResource('aedt', tableIndex);
  96.             
  97.             Try
  98.             {
  99.                 FailResError();
  100.  
  101.                 SignedByte savedState = HGetState(tableHandle);
  102.                 HLockHi(tableHandle);
  103.  
  104.                 long tableSize = GetHandleSize(tableHandle);
  105.                 FailMemError();
  106.  
  107.                 short tableElements = (short)(tableSize / sizeof(MAEventTableRec));
  108.  
  109.                 MAEventTablePointer tablePtr = (MAEventTablePointer) *tableHandle;
  110.  
  111.                 // Install a single event handler for all events 
  112.                 for (short eventIndex = 1; eventIndex <= tableElements; ++eventIndex, ++tablePtr)
  113.                     this->InstallAppleEventHandler(tablePtr->theClass, tablePtr->theID, tablePtr->theValue);
  114.  
  115.                 HSetState(tableHandle, savedState);
  116.             }
  117.             Catch(err)
  118.             {
  119.                 if (tableHandle)
  120.                     ReleaseResource(tableHandle);
  121.                 Throw(err);
  122.             }
  123.  
  124.             ReleaseResource(tableHandle);
  125.         }
  126.  
  127.  
  128.  
  129.  
  130.             // Install a universal object accessor
  131.         FailOSErr(AEInstallObjectAccessor(typeWildCard, typeWildCard,
  132.                                    NewOSLAccessorProc(TAppleObjectDispatcher::OSLObjectAccessorHandler),
  133.                                    0, false));
  134.  
  135.             // Set up the object support library callbacks
  136.         FailOSErr(AESetObjectCallbacks(
  137.                             NewOSLCompareProc(TAppleObjectDispatcher::OSLCompareObjectsHandler),
  138.                             NewOSLCountProc(TAppleObjectDispatcher::OSLCountObjectsHandler),
  139.                             NewOSLDisposeTokenProc(TAppleObjectDispatcher::OSLDisposeTokenHandler),    
  140.                             nil, nil, nil, nil));
  141.     }
  142.     Catch(err)
  143.     {
  144.         fgDispatcher = nil;
  145.         Throw(err);
  146.     }
  147. }
  148.  
  149.  
  150. MAppleObject* TAppleObjectDispatcher::ExtractObject(const AEDesc& descriptor)
  151. {
  152.     MAppleObject* result;
  153.  
  154.     if (descriptor.descriptorType == typeNull)
  155.         result = MAppleObject::GetDefaultAppleObject();
  156.     else
  157.         result = (MAppleObject*)descriptor.dataHandle;
  158.  
  159. #if DEBUG
  160.         if (descriptor.descriptorType != result->GetAppleClass())
  161.             DebugStr((ConstStr255Param) "Protocol error: object isn’t what it says it is");
  162. #endif
  163.  
  164.     return result;
  165. }
  166.  
  167.  
  168. MAppleObject* TAppleObjectDispatcher::GetTarget(const AppleEvent& message)
  169. {
  170.     // The target defaults to the application
  171.     MAppleObject* result = MAppleObject::GetDefaultAppleObject();
  172.  
  173.     Try
  174.     {
  175.         AEDesc    theDirectParameter;
  176.         FailOSErr(AEGetParamDesc(&message, keyDirectObject, typeWildCard, &theDirectParameter));
  177.         Try
  178.         {
  179.             // If the direct object is an object specifier, resolve it into
  180.             // an application domain object.
  181.             if (theDirectParameter.descriptorType == typeObjectSpecifier)
  182.                 result = this->ResolveSpecifier(theDirectParameter);
  183.         }
  184.         Catch(err)
  185.         {
  186.             OSErr ignoreErr = AEDisposeDesc(&theDirectParameter);
  187.             Throw(err);
  188.         }
  189.     }
  190.     Catch(err)
  191.     {
  192.         // It’s all right for there to be no direct object.  In that
  193.         // case, we stick with the default.
  194.         if (err != errAEDescNotFound)
  195.             Throw(err);
  196.     }
  197.  
  198. NoDescriptor:
  199.     FailNIL(result);
  200.  
  201.     return result;
  202. }
  203.  
  204.  
  205. void TAppleObjectDispatcher::StuffDescriptor(AEDesc& descriptor,
  206.                                              MAppleObject* object)
  207. {
  208.     descriptor.descriptorType = object->GetAppleClass();
  209.     descriptor.dataHandle = (Handle) object;
  210. }
  211.  
  212.  
  213. void TAppleObjectDispatcher::HandleAppleEvent(const AppleEvent& message,
  214.                                   AppleEvent& reply,
  215.                                   long refCon)
  216. {
  217.     MAppleObject* theTarget = this->GetTarget(message);
  218.     theTarget->DoAppleEvent(message, reply, refCon);
  219.  
  220.     // Dispose of the token object
  221.     AEDesc    fakeToken;
  222.     this->StuffDescriptor(fakeToken, theTarget);
  223.     FailOSErr(AEDisposeToken(&fakeToken));
  224. }
  225.  
  226.  
  227. void TAppleObjectDispatcher::AccessContainedObjects(DescType desiredClass,
  228.                                         const AEDesc& container,
  229.                                         DescType containerClass,
  230.                                         DescType form,
  231.                                         const AEDesc& selectionData,
  232.                                         AEDesc& value,
  233.                                         long /* refCon */)
  234. {
  235. #pragma unused(containerClass)
  236.     MAppleObject* containerObject = this->ExtractObject(container);
  237.  
  238. #if DEBUG
  239.         if (containerObject->GetAppleClass() != containerClass)
  240.             DebugStr((ConstStr255Param) "Protocol error: object isn’t what the AE Manager thinks it is");
  241. #endif
  242.  
  243.     Boolean    needsDisposal;
  244.     MAppleObject* resultObject = containerObject->GetContainedObject(desiredClass,
  245.                                                         form, selectionData,
  246.                                                         needsDisposal);
  247.     if (resultObject == nil)
  248.         FailOSErr(errAENoSuchObject);
  249.  
  250.     this->StuffDescriptor(value, resultObject);
  251.  
  252.     if (needsDisposal)
  253.         this->SetTokenObjectDisposal(resultObject, true);
  254. }
  255.  
  256.  
  257. long TAppleObjectDispatcher::CountObjects(const AEDesc& containerToken,
  258.                               DescType countObjectsOfType)
  259. {
  260.     MAppleObject* containerObject = this->ExtractObject(containerToken);
  261.     return containerObject->CountContainedObjects(countObjectsOfType);
  262. }
  263.  
  264. Boolean TAppleObjectDispatcher::CompareObjects(DescType operation,
  265.                                                const AEDesc& obj1,
  266.                                                const AEDesc& obj2)
  267. {
  268.     MAppleObject*    mObj1 = this->ExtractObject(obj1);
  269.     MAppleObject*    mObj2 = this->ExtractObject(obj2);
  270.  
  271.     return mObj1->CompareAppleObjects(operation, *mObj2);
  272. }
  273.  
  274. void TAppleObjectDispatcher::DisposeToken(AEDesc& unneededToken)
  275. {
  276.     MAppleObject*    theObject = this->ExtractObject(unneededToken);
  277.     if (this->GetTokenObjectDisposal(theObject))
  278.         delete theObject;
  279. }
  280.  
  281.  
  282. Boolean TAppleObjectDispatcher::GetTokenObjectDisposal(const MAppleObject* theObject)
  283. {
  284.     Boolean    result = false;
  285.  
  286.     // Search the list of objects to be disposed.  Return true if the object is
  287.     // in the list.
  288.     MAppleObject** curObj = *fDisposalList;
  289.     for (long i = 0; i < fDisposalListSize; i++, curObj++)
  290.     {
  291.         if (theObject == *curObj)
  292.         {
  293.             result = true;
  294.             break;
  295.         }
  296.     }
  297.  
  298.     return result;
  299. }
  300.  
  301.  
  302. void TAppleObjectDispatcher::SetTokenObjectDisposal(MAppleObject* theObject,
  303.                                                Boolean needsDisposal)
  304. {
  305.     // Search the list of objects to be disposed to see if it currently exists.
  306.     Boolean nilFound = false;
  307.     Boolean    found = false;
  308.     MAppleObject** curObj = *fDisposalList;
  309.     for (long i = 0; i < fDisposalListSize; i++, curObj++)
  310.     {
  311.         if (theObject == *curObj)
  312.         {
  313.             found = true;
  314.  
  315.             if (!needsDisposal)
  316.                 // remove it from the disposal list
  317.                 *curObj = nil;
  318.  
  319.             break;
  320.         }
  321.         else if (*curObj == nil)
  322.             nilFound = true;
  323.     }
  324.  
  325.     if (!found  &&  needsDisposal)
  326.     {
  327.         // it needs to be added to the list
  328.  
  329.         if (nilFound)
  330.         {
  331.             // we can sneak into a nil spot
  332.             curObj = *fDisposalList;
  333.             for (long i = 0; i < fDisposalListSize; i++, curObj++)
  334.             {
  335.                 if (*curObj == nil)
  336.                 {
  337.                     *curObj = theObject;
  338.                     break;
  339.                 }
  340.             }
  341.         }
  342.         else
  343.         {
  344.             // If the list hasn’t been created yet, create a zero-sized list
  345.             if (fDisposalList == nil)
  346.             {
  347.                 fDisposalList = (MAppleObject***) NewHandle(0);
  348.                 FailNIL(fDisposalList);
  349.             }
  350.  
  351.             Try
  352.             {
  353.                 fDisposalListSize++;
  354.                 SetHandleSize((Handle) fDisposalList, fDisposalListSize*sizeof(MAppleObject*));
  355.                 FailMemError();
  356.                 curObj = *fDisposalList;
  357.                 curObj += fDisposalListSize - 1;
  358.                 *curObj = theObject;
  359.             }
  360.             Catch(err)
  361.             {
  362.                 fDisposalListSize--;
  363.                 Throw(err);
  364.             }
  365.         }
  366.     }
  367. }
  368.  
  369.  
  370. MAppleObject* TAppleObjectDispatcher::ResolveSpecifier(AEDesc& objectSpecifier)
  371. {
  372.     AEDesc    tokenDesc;
  373.     FailOSErr(AEResolve(&objectSpecifier, kAEIDoMinimum, &tokenDesc));
  374.     MAppleObject* result = this->ExtractObject(tokenDesc);
  375.     return result;
  376. }
  377.  
  378.  
  379. pascal OSErr TAppleObjectDispatcher::AppleEventHandler(const AppleEvent* message,
  380.                                           AppleEvent* reply,
  381.                                           long refCon)
  382. {
  383.     OSErr    result = noErr;
  384.  
  385.     Try
  386.     {
  387.         GetDispatcher()->HandleAppleEvent(*message, *reply, refCon);
  388.     }
  389.     Catch(err)
  390.     {
  391.         result = err;
  392.     }
  393.  
  394.     return result;
  395. }
  396.  
  397. pascal OSErr TAppleObjectDispatcher::OSLObjectAccessorHandler(DescType desiredClass,
  398.                                          const AEDesc* container,
  399.                                          DescType containerClass,
  400.                                          DescType form,
  401.                                          const AEDesc* selectionData,
  402.                                          AEDesc* value,
  403.                                          long refCon)
  404. {
  405.     OSErr    result = noErr;
  406.  
  407.     Try
  408.     {
  409.         GetDispatcher()->AccessContainedObjects(desiredClass, *container,
  410.                                                 containerClass, form,
  411.                                                 *selectionData,
  412.                                                 *value, refCon);
  413.     }
  414.     Catch(err)
  415.     {
  416.         result = err;
  417.     }
  418.  
  419.     return result;
  420. }
  421.  
  422. pascal OSErr TAppleObjectDispatcher::OSLCountObjectsHandler(DescType countObjectsOfType,
  423.                                             DescType /* containerClass */,
  424.                                             const AEDesc* containerToken,
  425.                                             long* result)
  426. {
  427.     OSErr    theErr = noErr;
  428.  
  429.     Try
  430.     {
  431.         *result = GetDispatcher()->CountObjects(*containerToken, countObjectsOfType);
  432.     }
  433.     Catch(err)
  434.     {
  435.         theErr = err;
  436.     }
  437.  
  438.     return theErr;
  439. }
  440.  
  441.  
  442. pascal OSErr TAppleObjectDispatcher::OSLCompareObjectsHandler(DescType operation,
  443.                                          const AEDesc *obj1,
  444.                                          const AEDesc *obj2,
  445.                                          Boolean *answer)
  446. {
  447.     OSErr    result = noErr;
  448.  
  449.     Try
  450.     {
  451.         *answer = GetDispatcher()->CompareObjects(operation, *obj1, *obj2);
  452.     }
  453.     Catch(err)
  454.     {
  455.         result = err;
  456.     }
  457.  
  458.     return result;
  459. }
  460.  
  461.  
  462. pascal OSErr TAppleObjectDispatcher::OSLDisposeTokenHandler(AEDesc* unneededToken)
  463. {
  464.     OSErr    result = noErr;
  465.  
  466.     Try
  467.     {
  468.         GetDispatcher()->DisposeToken(*unneededToken);
  469.     }
  470.     Catch(err)
  471.     {
  472.         result = err;
  473.     }
  474.  
  475.     return result;
  476. }
  477.  
  478.  
  479. void TAppleObjectDispatcher::InstallAppleEventHandler(AEEventClass theClass,
  480.                                                      AEEventID theID,
  481.                                                      long refCon)
  482. {
  483.     FailOSErr(AEInstallEventHandler(theClass, theID,
  484.                                     NewAEEventHandlerProc(TAppleObjectDispatcher::AppleEventHandler),
  485.                                     refCon, false));
  486. }
  487.  
  488.  
  489. //--------------------------------------------------------------------------------
  490. // MAppleObject
  491. //--------------------------------------------------------------------------------
  492.  
  493. Boolean MAppleObject::fgInited = false;
  494. MAppleObject* MAppleObject::fgDefaultAppleObject = nil;
  495.  
  496.  
  497. MAppleObject::MAppleObject()
  498. {
  499. }
  500.  
  501.  
  502. MAppleObject::MAppleObject(const MAppleObject& /* copy */)
  503. {
  504. }
  505.  
  506.  
  507. MAppleObject::~MAppleObject()
  508. {
  509.     if (MAppleObject::GetDefaultAppleObject() == this)
  510.         MAppleObject::SetDefaultAppleObject(nil);
  511.  
  512.     TAppleObjectDispatcher::GetDispatcher()->SetTokenObjectDisposal(this, false);
  513. }
  514.  
  515.  
  516. MAppleObject& MAppleObject::operator=(const MAppleObject& /* assignTo */)
  517. {
  518.     return *this;
  519. }
  520.  
  521.  
  522. void MAppleObject::InitAppleObject(TAppleObjectDispatcher* dispatcher)
  523. {
  524.     // create a dispatcher if one wasn't passed in
  525.     if (dispatcher == nil)
  526.     {
  527.         dispatcher = new TAppleObjectDispatcher();
  528.         FailNIL(dispatcher);
  529.     }
  530.  
  531.     // Install the dispatcher
  532.     dispatcher->Install();
  533.  
  534.     fgInited = true;
  535. }
  536.  
  537.  
  538. long MAppleObject::CountContainedObjects(DescType /* ofType */)
  539. {
  540.     return 0;
  541. }
  542.  
  543.  
  544. Boolean MAppleObject::CompareAppleObjects(DescType /* operation */,
  545.                                           const MAppleObject& /* toWhat */)
  546. {
  547.     return false;
  548. }
  549.  
  550.  
  551. void MAppleObject::DoAppleEvent(const AppleEvent& /* message */,
  552.                                 AppleEvent& /* reply */, long /* refCon */)
  553. {
  554.     FailOSErr(errAEEventNotHandled);
  555. }
  556.  
  557.  
  558. MAppleObject* MAppleObject::GetContainedObject(DescType /* desiredType */,
  559.                                                DescType /* keyForm */,
  560.                                                const AEDesc& /* keyData */,
  561.                                                Boolean& /* needDisposal */)
  562. {
  563.     return nil;
  564. }
  565.  
  566.  
  567. void MAppleObject::GotRequiredParameters(const AppleEvent& theAppleEvent)
  568. {
  569.     // look for the keyMissedKeywordAttr, just to see if it's there
  570.     DescType    returnedType;
  571.     Size        actualSize;
  572.     OSErr theErr = AEGetAttributePtr(&theAppleEvent, keyMissedKeywordAttr,
  573.                                      typeWildCard, &returnedType, nil, 0,
  574.                                      &actualSize);
  575.  
  576.     if (theErr == noErr)
  577.     {
  578.         // Since the attribute exists, we missed a parameter somewhere.
  579.         FailOSErr(errAEParamMissed);
  580.     }
  581.     else if (theErr != errAEDescNotFound)
  582.     {
  583.         // The only error that is OK is to say that the descriptor was not
  584.         // found (indicating that we got all the parameters).  If any other
  585.         // error occurred, throw it.
  586.         FailOSErr(theErr);
  587.     }
  588. }
  589.  
  590.  
  591. void MAppleObject::SetDefaultAppleObject(MAppleObject* defaultObject)
  592. {
  593.     fgDefaultAppleObject = defaultObject;
  594. }
  595.